#include "BaseLog.h"
#include <sys/stat.h>
#include <assert.h>
#include <sys/types.h>

#ifdef WIN32
#include <direct.h>
#endif

#ifndef WIN32
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
#endif

#include "IDCreator.h"

CLog::CLog()
{
#ifndef WIN32
	m_strPath = "";
	m_cDelimiter = '/';
#else
	m_strPath = "";
	m_cDelimiter = '\\';
#endif
	
	m_fpLogFile =NULL;
	memset(&m_sCurTime, 0, sizeof(struct tm));
	m_dwSeqNo = 1;

	m_nStatus = 0;

}

CLog::~CLog()
{
	if(NULL != m_fpLogFile)
	{
		fclose(m_fpLogFile);
		m_fpLogFile = NULL;
	}

}

int CLog::WriteLog()
{
	//Gain and set current time
	if(0 != SetCurTime())
		return LOG_FAIL;

	if(LOG_SUCCESS != CheckLog())
	{
		if(NULL != m_fpLogFile)
		{
			fclose(m_fpLogFile);
			m_fpLogFile = NULL;
		}

		//Open a new log file
		if(LOG_SUCCESS != OpenFile())
			return LOG_FAIL;

		//write head info
		WriteHeader();
		
		m_dwSeqNo = 1; //reset the sequence number
	}

	//Write Row Header
	WriteRowHeader();

	//write detial item info
	WriteItems();

	if(m_fpLogFile != NULL)
		fflush(m_fpLogFile);
	
	return LOG_SUCCESS;
}

int CLog::WriteHeader()
{
	if(m_nStatus != 1 && m_nStatus != 3)
		return LOG_FAIL;

	if(NULL == m_fpLogFile)
		return LOG_FAIL;
	
	fprintf(m_fpLogFile, "#Log File Created On: %02d/%02d/%4d %02d:%02d:%02d\n", 
		m_sCurTime.tm_mon+1, m_sCurTime.tm_mday, m_sCurTime.tm_year+1900,
		m_sCurTime.tm_hour, m_sCurTime.tm_min, m_sCurTime.tm_sec);
	
	fprintf(m_fpLogFile, "#Software: Genius Streaming Server\n");
	
	fprintf(m_fpLogFile, "#Version: 1.0\n");
	
	fprintf(m_fpLogFile, "#Date: %4d-%02d-%02d %02d:%02d:%02d\n", 
		m_sCurTime.tm_year+1900, m_sCurTime.tm_mon+1, m_sCurTime.tm_mday,
		m_sCurTime.tm_hour, m_sCurTime.tm_min, m_sCurTime.tm_sec);
	
	fprintf(m_fpLogFile, "#Remark: all time values are in Local Time\n");

	return LOG_SUCCESS;
}

int CLog::WriteRowHeader()
{
	if(m_nStatus != 1 && m_nStatus != 3)
		return LOG_FAIL;
	
	if(m_fpLogFile == NULL)
		return LOG_FAIL;

	//Output sequence number and date/time
	fprintf(m_fpLogFile, "%-10d ", m_dwSeqNo++);
	fprintf(m_fpLogFile, "%04d-%02d-%02d %02d:%02d:%02d   ", 
		m_sCurTime.tm_year+1900, m_sCurTime.tm_mon+1, m_sCurTime.tm_mday,
		m_sCurTime.tm_hour, m_sCurTime.tm_min, m_sCurTime.tm_sec);
	
	return LOG_SUCCESS;	
}
int CLog::SetCurTime()
{
	time_t tTime;
	struct tm *pTmTime;
	
	time(&tTime);
	
	pTmTime = localtime(&tTime);
	if(NULL == pTmTime)
		return LOG_FAIL;

	memcpy(&m_sCurTime, pTmTime, sizeof(struct tm));

	return LOG_SUCCESS;
}


int CLog::CheckLog()
{
	//get created time of log file
	if(NULL == m_fpLogFile)
		return LOG_FAIL;
	
	int fd = fileno(m_fpLogFile);
	struct stat sbuf;
	int retno;
	retno = fstat(fd,&sbuf);
	struct tm time_tmp;
	struct tm *time_create;
	
	time_create = localtime(&sbuf.st_ctime);
	memcpy(&time_tmp,time_create,sizeof(struct tm));
	time_create = &time_tmp;

	//if file is deleted
	//or current time not eq the create time of file
	//or file size beyond 64k
	if(sbuf.st_nlink == 0 || 
		time_create->tm_year != m_sCurTime.tm_year ||
		time_create->tm_yday != m_sCurTime.tm_yday ||
		sbuf.st_size >= LOG_MAX_FILE_SIZE)
	{
		return LOG_FAIL;
	}
	
	return LOG_SUCCESS;
}

int CLog::OpenFile()
{
	if(m_nStatus != 1 && m_nStatus != 3)
		return LOG_SUCCESS;

	if(0 != MakeDir())
	{
		printf("Build log directoris failed!\n");
		return LOG_FAIL;
	}

	if(0 != FileName())
		return LOG_FAIL;
	
	m_fpLogFile = fopen(m_strFileName.c_str(), "w+");
	if(m_fpLogFile == NULL)
	{
//		perror("Open file for log failed!");
		return LOG_FAIL;
	}

	ChangeOwn(m_strFileName.c_str(), LOG_USER_NAME);

	return LOG_SUCCESS;
}

void CLog::SetPath(const string strPath)
{
	assert(strPath.length() > 0);

	m_strPath += strPath;

	if(m_strPath.at(m_strPath.length()-1) != m_cDelimiter)
		m_strPath += m_cDelimiter;
}

int CLog::ChangeOwn(const char *PathName, const char *UserName)
{
#ifndef WIN32
	struct passwd *pPwd;
	
	pPwd = getpwnam(UserName);
	if(pPwd != NULL)
	{
		int uid = pPwd->pw_uid;
		int gid = pPwd->pw_gid;
		
		return chown(PathName, uid, gid);
	}
	return -1;
#endif
	return 0;
}

int CLog::MakeDir()
{
	char Buf[256];
	memset(Buf, 0, sizeof(Buf));
	
	sprintf(Buf, "%4d%02d%02d", m_sCurTime.tm_year+1900,m_sCurTime.tm_mon+1,m_sCurTime.tm_mday);

	SetPath(Buf);
	
	long lBeginPos = -1;
	long lEndPos = -1;
	lBeginPos = m_strPath.find(m_cDelimiter);
	if(-1 != lBeginPos)
	{
		lEndPos = m_strPath.find(m_cDelimiter, lBeginPos+1);
	}
	
	string strDirName;
	while (lBeginPos != -1 && lEndPos != -1)
	{
		strDirName = m_strPath.substr(0, lEndPos);
		struct stat theStatBuffer;		
		//if this directory doesn't exist, will create it
		if (stat(strDirName.c_str(), &theStatBuffer) == -1)
		{
#ifdef WIN32
			if (mkdir(strDirName.c_str()) == -1)
			{
				return LOG_FAIL;
			}
#else
			if (mkdir(strDirName.c_str(), S_IRWXU) == -1)
			{
				return LOG_FAIL;
			}
#endif
		}
		
#ifdef WIN32
		else if (!(theStatBuffer.st_mode & _S_IFDIR)) /* MSVC++ doesn't define the S_ISDIR macro*/
			return LOG_SUCCESS; /* there is a file at this point in the path!*/
#else
		else if (!S_ISDIR(theStatBuffer.st_mode))
			return LOG_SUCCESS;/*there is a file at this point in the path!*/
#endif
		
		ChangeOwn(strDirName.c_str(), LOG_USER_NAME);

		lEndPos = m_strPath.find(m_cDelimiter, lEndPos+1);
	}
	
	return LOG_SUCCESS;
}

int CLog::FileName()
{
	char Buf[256];
	memset(Buf, 0, sizeof(Buf));
	
	if(m_strPath == "")
		return LOG_FAIL;
	
	sprintf(Buf,"%s%04d%02d%02d%02d%02d%02d.log",m_strPath.c_str(),m_sCurTime.tm_year+1900,m_sCurTime.tm_mon+1,m_sCurTime.tm_mday,m_sCurTime.tm_hour,m_sCurTime.tm_min,m_sCurTime.tm_sec);
	
	m_strFileName = Buf;

	return LOG_SUCCESS;
}


FILE* CreateDebugFile(const string strName)
{
	FILE *ycb_fp = NULL;
	char buf[32];
	sprintf(buf, "%s%I64d.xls", strName.c_str(), CIDCreator::GetPeerID());
	string filename = "d:\\";
	filename += buf;
	ycb_fp = fopen(filename.c_str(), "w+");

	return ycb_fp;
}